<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ChatGPT Interface</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/quasar@1.20/dist/quasar.min.css">
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
<div id="appper">
    <div class="chatgpt">
        <div class="messages-container">
            <div class="messages">
                <div v-for="(message, index) in formItem.messages" :key="index" :class="{'message-user': message.role === 'user', 'message-assistant': message.role !== 'user'}">
                     <div class="message-content" :class="{'message-user': message.role === 'user', 'message-assistant': message.role !== 'user'}">
                    <q-avatar :class="{'right': message.role === 'user', 'left': message.role !== 'user'}">
                        <img :src="message.role === 'user' ? getUserAvatar() : 'https://uploads-ssl.webflow.com/657c661418a503e0b43c9905/664781d921ff30411c47952a_%E6%99%BA%E8%83%BD%E5%8A%A9%E6%89%8B-copy.svg'" />
                    </q-avatar>
                    <div class="message-content-per" v-html="renderMarkdown(message.content)"></div>
                    <q-btn floating mini @click="copyMessage(index)" icon="content_copy" class="copy-button"></q-btn>
                    </div>
                </div>
            </div>
        </div>

        <div style="text-align: center">
            <q-btn class="button" color="primary" @click="clearDialog">清空对话</q-btn>
        </div>

        <div class="form-container">
            <q-form :model="formItem" class="form">
                <q-form-item label="模型 ：">
                    <q-select v-model="formItem.model" :options="modelList" />
                </q-form-item>
                <q-form-item>
                    <q-input v-model="formItem.input" type="textarea" :rows="5" placeholder="请输入..." @keydown="onKeyDown" />
                </q-form-item>
                <q-form-item style="text-align: right;">
                    <q-btn class="button" @click="clearInput">清空输入</q-btn>
                    <q-btn class="button" color="primary" @click="submit" :loading="formItem.loading">提交</q-btn>
                </q-form-item>
            </q-form>
        </div>
    </div>
</div>





<script src="https://cdn.jsdelivr.net/npm/showdown/dist/showdown.min.js"></script>

<script src="https://wxserver.cards120.com/static/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/quasar@1.20/dist/quasar.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

<script>
new Vue({
    el: '#appper',
    components: {
        QForm: Quasar.components.QForm,
        QSelect: Quasar.components.QSelect,
        QInput: Quasar.components.QInput,
        QTimeline: Quasar.components.QTimeline,
        QTimelineEntry: Quasar.components.QTimelineEntry,
        QBtn: Quasar.components.QBtn,
        QCard: Quasar.components.QCard,
        QCardSection: Quasar.components.QCardSection,
        QMarkdown: Quasar.components.QMarkdown,
        QAvatar: Quasar.components.QAvatar,
        VueMarkdown: window['VueMarkdown']
    },
    methods: {
// 复制消息内容
        copyMessage(index) {
            const messageContent = this.formItem.messages[index].content;
            const tempTextarea = document.createElement('textarea');
            tempTextarea.value = messageContent;
            document.body.appendChild(tempTextarea);
            tempTextarea.select();
            document.execCommand('copy');
            document.body.removeChild(tempTextarea);
            this.$q.notify({
                message: '内容已复制',
                color: 'positive',
            });
        },

        getUserAvatar() {
            // 从localStorage获取主题信息
            const themeStr = localStorage.getItem('zhuti');
            if (themeStr) {
                try {
                    const themeObj = JSON.parse(themeStr);
                    return themeObj.personalImg; // 返回头像URL
                } catch (e) {
                    console.error('解析主题信息失败:', e);
                }
            }
            return 'default_avatar.png'; // 如果没有获取到头像，则返回一个默认头像
        },
        renderMarkdown(markdownText) {
            const converter = new showdown.Converter({
                extensions: [],
                openLinksInNewWindow: true, // 如果需要，使链接在新窗口中打开
                simplifiedAutoLink: true,
                literalMidWordUnderscores: true,
                strikethrough: true,
                tables: true,
                tablesHeaderId: true,
                ghCodeBlocks: true,
                tasklists: true,
                smoothLivePreview: true,
                simpleLineBreaks: true,
                parseImgDimensions: true,
                emoji: true,
                underline: true,
                highlight: function (code, lang) {
                    return hljs.highlightAuto(code, [lang]).value;
                }
            });
            return converter.makeHtml(markdownText);
        },
        chooseColor(role) {
            switch (role) {
                case 'user': return 'blue';
                default: return 'green';
            }
        },
        clearDialog() {
            this.formItem.messages = [
                {
                    role: 'assistant',
                    content: '您好，请问有什么可以帮到您？',
                },
            ];
        },
        clearInput() {
            this.formItem.input = '';
        },
        onKeyDown(event) {
            if (event.ctrlKey && event.keyCode === 13) {
                this.submit();
            }
        },
        // 添加新消息到 messages 数组中
        addMessage(newMessage) {
            // 使用 $set 更新数组的特定索引
            this.$set(this.formItem.messages, this.formItem.messages.length, newMessage);
        },
        async submit() {


            const themeStr = localStorage.getItem('zhuti');
            let vipIsValid = true; // 默认会员有效

            if (themeStr) {
                try {
                    const themeObj = JSON.parse(themeStr);
                    if (themeObj.vipdate) {  // 检查vipdate属性是否存在
                        let vipDate = new Date(themeObj.vipdate);
                        if (!isNaN(vipDate.getTime())) {  // 检查vipDate是否为有效的日期
                            vipDate.setHours(0, 0, 0, 0);  // 清除时分秒毫秒
                            const today = new Date();
                            today.setHours(0, 0, 0, 0);  // 对当前日期也清除时分秒毫秒以确保公平比较
                            vipIsValid = vipDate >= today;
                        } else {
                            console.error('无效的vipdate:', themeObj.vipdate);
                            vipIsValid = false; // 如果vipdate无效，认为会员无效
                        }
                    }else{
                         console.error('无效的vipdate:', themeObj.vipdate);
                         vipIsValid = false; // 如果vipdate无效，认为会员无效
                    }
                } catch (e) {
                    console.error('解析主题信息失败:', e);
                }
            }else{
                         console.error('无效的vipdate:', themeObj.vipdate);
                         vipIsValid = false; // 如果vipdate无效，认为会员无效
                    }

            if (!vipIsValid) {
                Swal.fire({
                    icon: 'error',
                    title: '会员服务已到期或不可用',
                    text: '需要开通会员才能继续使用AI总结功能。',
                });
                return;
            }







            if (!this.formItem.input) {
                this.$q.notify({
                    message: '请输入',
                    color: 'negative',
                });
                return;
            } else {
                this.formItem.loading = true;
                this.addMessage({
                    role: 'user',
                    content: this.formItem.input,
                });
                //https://worker-plain-glitter-b714.shikai327.workers.dev/api/openai/v1/chat/completions
                let apiEndpoint = 'https://chatgpt.yinziming.com/api/openai/v1/chat/completions'; // 指定的 API 端点
                var chatArr = this.formItem.messages.slice(1, this.formItem.messages.length)
                chatArr.forEach(item => {
                    item.content = item.content.replaceAll(this.formItem.context, '');
                });

                var copiedArr = JSON.parse(JSON.stringify(chatArr));

                // 检查数组是否为空
                if (copiedArr.length > 0) {
                    // 获取数组的最后一个元素
                    let lastMessage = copiedArr[copiedArr.length - 1];

                    // 将 this.formItem.context 拼接到最后一个消息的内容前面
                    lastMessage.content = this.formItem.context + lastMessage.content;
                }

                // 准备请求选项
                const requestOptions = {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        'Accept': 'text/event-stream'  // 重要：指定期望的响应格式
                    },
                    body: JSON.stringify({
                        messages: copiedArr,
                        model: this.formItem.model
                    })
                };

                try {
                    const response = await fetch(apiEndpoint, requestOptions);
                    if (!response.ok) {
                        throw new Error('网络请求失败');
                    }

                    // 读取流式数据
                    const reader = response.body.getReader();
                    const decoder = new TextDecoder('utf-8');
                    let buffer = '';
                    const readStream = async () => {
                        var done1 = false
                        while (!done1) {
                            let { done, value } = await reader.read();

                            buffer =buffer+ decoder.decode(value, {stream: true});;
                            done1 = done
                        }
                        var chunk = buffer
                        console.log(chunk)
                        console.log(JSON.parse(chunk.replace(/data:/g, "")))
                        var content = JSON.parse(chunk.replace(/data:/g, "")).choices[0].message.content
                        console.log(content)
                        this.addMessage({
                            role: 'assistant',
                            content: content,
                        });
                        ({ done, value } = await reader.read());


                        reader.releaseLock();
                        this.formItem.loading = false;
                        console.log('Stream complete');
                    };

                    readStream();

                } catch (error) {
                    console.error("请求错误", error);
                    this.$q.notify({
                        message: '请求失败',
                        color: 'negative',
                    });
                    this.formItem.loading = false;
                }
            }
        }



    },
    data() {
        return {
            formItem: {
                messages: [
                    {
                        role: 'assistant',
                        content: '您好，请问有什么可以帮到您？',
                    },
                ],
                model: 'gpt-3.5-turbo',
                input: '',
                loading: false,
                context: '你要知道你的角色，然后在回答中扮演这个角色，这是你这个角色的基础信息，你是人工智能助手kerly。之后你要用这个回答之后的问题，当前我的问题如下：',
            },
            modelList: [
                'gpt-3.5-turbo',
                'gpt-4',
                'gpt-4-32k',
                'chatgml-6'
            ],
        };
    },
    mounted() {
        // 初始化或调用的代码
    }
});

</script>

<style>
    .messages-container {
        height: 400px; /* 可根据需要调整高度 */
        overflow-y: auto;
        padding: 10px;
    }

    .messages {
        display: flex;
        flex-direction: column;
    }

    .message-content {
        display: flex;
        max-width: 70%;
        margin-bottom: 10px;
    }

    .message-user {
        align-items: flex-end;
        display: flex;
        justify-content: flex-end;
    }

    .message-assistant {
        align-items: flex-start;
        display: flex;
        justify-content: flex-start;
    }

    .message-content .message-content-per {
        padding: 8px;
        background-color: #f9f9f9;
        border-radius: 10px;
        border: 1px solid #ddd;
        margin: 0;
    }

    .q-avatar {
        margin-left: 10px;
        margin-right: 10px;
    }

    .q-avatar.right {
        order: 2;
    }

    .q-avatar.left {
        order: -1;
    }

    .chatgpt {
        border: 1px solid #ccc;
        background: #ffffff;
        position: relative;
        overflow: hidden;
        display: flex;
        flex-direction: column;
        height: 100%; /* 使 chatgpt 元素高度填满父容器 */
    }

    .form-container {
        padding: 10px;
        border-top: 1px solid #ccc;
    }

    .form {
        margin: 0;
    }

    /*chatgpt代码格式修正*/
    pre, code {
        font-family: 'Fira Code', 'Consolas', 'Monaco', 'Andale Mono', 'Ubuntu Mono', monospace;
        font-size: 0.85em; /* 减小字体大小 */
        color: #dcdcdc; /* 浅灰色文字，适合深色背景 */
        background-color: #1e1e1e; /* 深色背景 */
        border-radius: 5px;
        padding: 0.5em; /* 减少内边距 */
    }

    pre {
        margin: 0.5em 0; /* 调整上下外边距 */
        overflow: auto;
        line-height: 1.2; /* 更紧凑的行高 */
        border: 1px solid #333; /* 深色边框 */
    }

    code {
        display: block;
        white-space: pre-wrap;
        overflow-x: auto; /* 超出部分显示水平滚动条 */


    }



    /* 特别适用于行内代码的样式，如果有需要 */
    .inline-code {
        padding: 0.2em 0.4em; /* 减少内边距 */
        background-color: #272822; /* 略有差异的背景色以区分 */
        border-radius: 3px;
        color: #f8f8f2;
    }
    .message-assistant .message-content-per p {
        font-size: 0.85em; /* 减小字体大小 */
    }

    .message-content-per {
        padding-bottom: 0px!important;
    }
    .chatgpt {
        display: flex;
        flex-direction: column;
        height: 100vh;  /* 使用视口高度，确保占满整个屏幕 */
        border: 1px solid #ccc;
        background: #ffffff;
        position: relative;
        overflow: hidden;
    }

    .messages-container {
        flex: 1;  /* 允许这个容器增长以填充所有可用空间 */
        overflow-y: auto;  /* 当内容超过容器高度时显示滚动条 */
        padding: 10px;
    }

    .form-container {
        padding: 10px;
        border-top: 1px solid #ccc;  /* 顶部边界清晰可见 */
    }



/*    */
.message-content {
    position: relative;
    display: flex;
    align-items: center;
    min-height: 50px;

}

.message-content-per {
    flex-grow: 1;
    padding: 8px;
    background-color: #f9f9f9;
    border-radius: 10px;
    border: 1px solid #ddd;
    margin: 0 10px;
}

/* 默认助理消息，按钮在右侧 */
.copy-button {
    position: absolute;
    right: 0;
    top: 0;
    transform: translateY(-100%);
    margin-top: -15px;
    margin-right: 8px;
    border-radius: 50%;
    background-color: #FFFFFF; /* 按钮背景颜色 */
    box-shadow: 0 2px 5px rgba(0,0,0,0.2); /* 添加阴影效果 */
    width: 0px; /* 按钮宽度 */
    height: 0px; /* 按钮高度 */
    display: flex;
    align-items: center;
    justify-content: center;
        opacity: 0;  /* 默认不可见 */
    transition: opacity 0.3s;  /* 平滑过渡效果 */

}

/* 用户消息，按钮在左侧 */
.message-user .copy-button {
    left: 0;
    right: auto;
    transform: translateY(-100%);
}

.copy-button:hover {
    background-color: #e1e1e1; /* 鼠标悬停时的背景颜色 */
    transform: translateY(-110%) scale(1.1); /* 鼠标悬停时稍微放大并上移 */
}
.message-content:hover .copy-button {
    opacity: 0.3;  /* 悬浮时变为可见 */
}





</style>
</body>
</html>

